import readline from 'readline'

/**
 * 隐私信息输入
 */
export const privacyInput = (options: PrivacyInputOptions = {}) => {
  const {
    prompt = 'password: ',
    mask = '*',
    maxLength = 16,
    clearPrompt = true,
    clearPromptAfterDestroy = true
  } = options

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    terminal: true
  })

  let destroyed = false

  const destroy = () => {
    destroyed = true
    rl.close()
    if (clearPromptAfterDestroy) {
      clearPromptFn(true)
    }
  }

  // 清除密码提示
  const clearPromptFn = (noReturn = false) => {
    if (noReturn) {
      readline.cursorTo(process.stdout, 0)
    } else {
      readline.moveCursor(process.stdout, 0, -1)
    }
    readline.clearLine(process.stdout, 0)
  }

  const result = new Promise<string>((resolve) => {
    let text = ''

    // 监听用户输入
    process.stdin.on('keypress', (char, key) => {
      if (!key) {
        return
      }

      if (key.name === 'return') {
        rl.close()
      } else if (key.name === 'c' && key.ctrl) {
        // Ctrl+C
        process.exit()
      } else if (key.name === 'backspace') {
        // Backspace
        if (text.length > 0) {
          text = text.slice(0, -1)
          updatePasswordInput()
        }
      } else if (!key.ctrl && !key.meta && !key.alt) {
        if (text.length < maxLength) {
          text += char
        }
        updatePasswordInput()
      }
    })

    // 更新密码输入的显示
    const updatePasswordInput = () => {
      readline.cursorTo(process.stdout, 0)
      readline.clearLine(process.stdout, 1)
      process.stdout.write(prompt + mask.repeat(text.length))
    }

    // 提示用户输入密码
    process.stdout.write(prompt)

    rl.on('close', () => {
      if (destroyed) return
      if (clearPrompt) {
        clearPromptFn()
      }
      resolve(text)
    })
  })

  return { result, destroy }
}

export type PrivacyInputOptions = {
  prompt?: string
  mask?: string
  maxLength?: number
  clearPrompt?: boolean
  clearPromptAfterDestroy?: boolean
}
